/*
 * Copyright 2007 National Bioinformatics Network
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package dgbgui.modeldocument.primitives;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import org.jgrapht.DirectedGraph;
import org.jgrapht.graph.DefaultDirectedGraph;

import dgbgui.exceptions.NoUniqueDGBQLException;

public class Graph extends Primitive {
    
    public Graph() {
        super(0);
        m_primtiveGraph = new DefaultDirectedGraph<Primitive,DefaultAnnotatedEdge>(DefaultAnnotatedEdge.class);
    }
    
    public Graph(DirectedGraph<Primitive,DefaultAnnotatedEdge> graph) {
        super(0);
        m_primtiveGraph = graph;
    }
    
    public Set<Primitive> vertexSet() {
        return m_primtiveGraph.vertexSet();
    }
    
    public Set<DefaultAnnotatedEdge> edgeSet() {
        return m_primtiveGraph.edgeSet();
    }
    
    public Primitive getEdgeSource(DefaultAnnotatedEdge e) {
        return m_primtiveGraph.getEdgeSource(e);
    }
    
    public Primitive getEdgeTarget(DefaultAnnotatedEdge e) {
        return m_primtiveGraph.getEdgeTarget(e);
    }
    
    public Set<Primitive> getInVertices(Primitive to) {
        Set<DefaultAnnotatedEdge> edges = m_primtiveGraph.incomingEdgesOf(to);
        Set<Primitive> inVertices = new HashSet<Primitive>();
        for ( DefaultAnnotatedEdge edge : edges ) {
            inVertices.add( m_primtiveGraph.getEdgeSource(edge));
        }
        return inVertices;
    }
    
    public Set<Primitive> getOutVertices(Primitive from) {
        Set<DefaultAnnotatedEdge> edges = m_primtiveGraph.outgoingEdgesOf(from);
        Set<Primitive> outVertices = new HashSet<Primitive>();
        for ( DefaultAnnotatedEdge edge : edges ) {
            outVertices.add( m_primtiveGraph.getEdgeTarget(edge));
        }
        return outVertices;
    }
    
    public String getEdgeAnnotation(Primitive source, Primitive target) {
        return m_primtiveGraph.getEdge(source, target).getAnnotation();
    }
    
    public Object clone() {
        Graph o = null;
        o = (Graph)super.clone();
        
        o.m_primtiveGraph = new DefaultDirectedGraph<Primitive,DefaultAnnotatedEdge>(DefaultAnnotatedEdge.class);
        Map<Primitive,Primitive> cloneMap = new HashMap<Primitive,Primitive>();
        for ( Primitive p : m_primtiveGraph.vertexSet() ) {
            Primitive clone = (Primitive)p.clone();
            cloneMap.put(p,clone);
            o.m_primtiveGraph.addVertex(clone); 
        }
        
        for ( DefaultAnnotatedEdge e : m_primtiveGraph.edgeSet() ) {
            o.m_primtiveGraph.addEdge(
                    cloneMap.get(m_primtiveGraph.getEdgeSource(e)),
                    cloneMap.get(m_primtiveGraph.getEdgeTarget(e)),
                    new DefaultAnnotatedEdge(e.getAnnotation()));
        }
        
        return o;
    }
    
    public String summary() {
        return "Graph: " + m_primtiveGraph.vertexSet().size() + " vertices, " + m_primtiveGraph.edgeSet().size() + " edges"; 
    }
    
    public String getDGBQLForPrimitive() throws NoUniqueDGBQLException {
        throw new NoUniqueDGBQLException(this);
    }
    
    // --------------- Serialization ----------------
    
    /**
     * First serilization version
     */
    private static final long serialVersionUID = 1L;
    
    // ------------------ Fields --------------------
    
    DirectedGraph<Primitive,DefaultAnnotatedEdge> m_primtiveGraph = new DefaultDirectedGraph<Primitive,DefaultAnnotatedEdge>(DefaultAnnotatedEdge.class);



}
